package com.ewei.web.authority.shiro;

import java.util.concurrent.atomic.AtomicInteger;

import javax.annotation.Resource;


import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;

import com.ewei.web.authority.shiro.stateless.StatelessToken;
import com.ewei.web.authority.utils.TokenUtils;
/**
 * shiro凭证验证方法（防止暴力解锁，增加安全性）
 * @author David
 *
 */
public class LimitedHashCredentialsMatcher extends HashedCredentialsMatcher{
	@Resource
	private TokenUtils tokenUtil;
	public LimitedHashCredentialsMatcher(CacheManager manager){
		this.pwdRetryCache = manager.getCache("pwdPetryCache");
	}
	//只适用于单节点，不适用于集群
	private Cache<String, AtomicInteger> pwdRetryCache;
	//最大容许尝试次数
	private static final Integer maxCount = 5;
	@Override
	public boolean doCredentialsMatch(AuthenticationToken token,
			AuthenticationInfo info) {
		String username = (String)token.getPrincipal();
		if(token instanceof UsernamePasswordToken){//用户密码登陆凭证匹配
			AtomicInteger count = pwdRetryCache.get(username);
			if(null == count){
				count = new AtomicInteger(0);
				pwdRetryCache.put(username, count); //运用缓存处理记录密码重试次数
			}
			if(count.incrementAndGet()>maxCount){
				throw new ExcessiveAttemptsException();//登录失败次数过多
			}
			boolean isMatch =  super.doCredentialsMatch(token, info);
			if(isMatch){
				pwdRetryCache.remove(username);//清除缓存
			}
			System.out.println("Credential result:"+isMatch);
			return isMatch;
		}else if(token instanceof StatelessToken){//Cookie(无状态)登陆凭证匹配
			StatelessToken statelessToken =(StatelessToken)token;
			boolean bool = tokenUtil.validate(statelessToken.getTokenValue(),
					statelessToken.getAuth());
			if(!bool){
				throw new IncorrectCredentialsException();//错误的凭证
			}
			return true;
		}
		return false; //凭证匹配失败
	}
	
}
